package control;

import entity.EEntity;
import entity.ERegister;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Observer;
import mediator.MDataStreamHandler;
import mediator.MFileCommunication;
import mediator.MVideoReader;
import server.SBroadcaster;
import server.SClient;
import server.SNewConnectionsHandler;

public class CControl
{

    private EEntity eEntity;
    private MFileCommunication mFileCommunication;
    private MVideoReader mVideoReader;
    private MDataStreamHandler mDataStream;
    private String mapPath = "maps/";
    private String rootPath = "";
    private SNewConnectionsHandler sNewConnectionsHandler;
    private SBroadcaster sBroadcaster;

    public CControl()
    {
        rootPath = new File(CControl.class.
                getProtectionDomain().getCodeSource().getLocation().getPath()).
                getParent() + "/";
        eEntity = new EEntity();
        mFileCommunication = new MFileCommunication(eEntity, getRootPath());
        String videourl = mFileCommunication.getSettingsParameter("videourl");   
        
        // Read connection string
        int port = 0;
        try
        {
            port = Integer.parseInt(mFileCommunication.getSettingsParameter(
                    "dataport"));
        }
        catch (Exception e)
        {
        }
        String address = mFileCommunication.getSettingsParameter("dataaddress");
        
        mDataStream = new MDataStreamHandler(eEntity, mFileCommunication, address, port);
        mVideoReader = new MVideoReader(videourl);
        sNewConnectionsHandler = new SNewConnectionsHandler(this);
        sBroadcaster = new SBroadcaster(this);
        mDataStream.addObserver(sBroadcaster);
        sNewConnectionsHandler.addObserver(sBroadcaster);

    }
    
    public void startStreaming()
    {
        // Read connection string
        int port = 0;
        try
        {
            port = Integer.parseInt(mFileCommunication.getSettingsParameter(
                    "dataport"));
        }
        catch (Exception e)
        {
        }
        String address = mFileCommunication.getSettingsParameter("dataaddress");
        mDataStream.startStreaming(address, port);
        
        //mVideoReader.startStreaming();
    }
    
    public void stopStreaming(){
        mDataStream.stopStreaming();
        //mVideoReader.stopStreaming();
    }

    public String[] getPlotableRegisters()
    {
        return eEntity.getPlotableRegisters();
    }

    public double[] getRegisterBoundaries(String register)
    {
        return eEntity.getRegisterBoundaries(register);
    }

    public String getSettingsParameter(String parameter)
    {
        return mFileCommunication.getSettingsParameter(parameter);
    }

    public boolean setSettingsParameter(String parameter, String value)
    {
        return mFileCommunication.setSettingsParameter(parameter, value);
    }

    public boolean setGraphSettingsFile(String fileName)
    {
        return mFileCommunication.setGraphSettingsFile(fileName);
    }

    public String getGraphSettingsParameter(String parameter)
    {
        return mFileCommunication.getGraphSettingsParameter(parameter);
    }

    public boolean setGraphSettingsParameter(String parameter, String value)
    {
        return mFileCommunication.setGraphSettingsParameter(parameter, value);
    }

    public String getRegisterUnit(String register)
    {
        return eEntity.getRegisterUnit(register);
    }

    public String getRegisterName(String node, String startsWith)
    {
        return eEntity.getRegisterName(node, startsWith);
    }

    public String[] getNodeList()
    {
        return eEntity.getNodeList();
    }

    public HashMap<String, ERegister> getRegisters(String node)
    {
        return eEntity.getRegisters(node);
    }

    public void addStreamObserver(Observer observer)
    {
        mDataStream.addObserver(observer);
    }

    public void addRegisterObserver(String node, String register,
                                    Observer observer)
    {
        eEntity.addObserver(node, register, observer);
    }

    public void removeRegisterObserver(String node, String register,
                                       Observer observer)
    {
        eEntity.removeObserver(node, register, observer);
    }

    public void addRegisterObserver(String register, Observer observer)
    {
        eEntity.addObserver(register, observer);
    }

    public void removeRegisterObserver(String register, Observer observer)
    {
        eEntity.removeObserver(register, observer);
    }

    public void addVideoObserver(Observer obs)
    {
        mVideoReader.addObserver(obs);
    }

    public void removeVideoObserver(Observer obs)
    {
        mVideoReader.removeObserver(obs);
    }

    public void addStreamStatusObserver(Observer obs)
    {
        mDataStream.addStatusObserver(obs);
    }

    public void removeStreamStatusObserver(Observer obs)
    {
        mDataStream.deleteStatusObserver(obs);
    }

    public void addVideoStatusObserver(Observer obs)
    {
        mVideoReader.addStatusObserver(obs);
    }

    public void removeVideoStatusObserver(Observer obs)
    {
        mVideoReader.deleteStatusObserver(obs);
    }
    
    public void addServerStatusObserver(Observer obs)
    {
        sNewConnectionsHandler.addObserver(obs);
    }
    
    public void removeServerStatusObserver(Observer obs)
    {
        sNewConnectionsHandler.deleteObserver(obs);
    }

    public void addError(String line)
    {
        mFileCommunication.addError(line);
    }

    public String getRootPath()
    {
        return rootPath;
    }

    public Object[] getMaps()
    {
        String file;
        File folder = new File(getRootPath() + mapPath);
        File[] listOfFiles = folder.listFiles();
        ArrayList<String> files = new ArrayList<String>();

        if (listOfFiles != null)
        {
            for (int i = 0; i < listOfFiles.length; i++)
            {

                if (listOfFiles[i].isFile())
                {
                    file = listOfFiles[i].getName();
                    if (file.toLowerCase().endsWith(".png")
                            || file.toLowerCase().endsWith(".jpg")
                            || file.toLowerCase().endsWith(".jpeg")
                            || file.toLowerCase().endsWith(".jpg")
                            || file.toLowerCase().endsWith(".gif"))
                    {
                        files.add(file);
                    }
                }
            }
        }

        return (Object[]) files.toArray();
    }

    public void addClient(SClient client)
    {
        sBroadcaster.addClient(client);
    }

    public void removeClient(SClient client)
    {
        sBroadcaster.removeClient(client);
    }

    public void startServer(int port)
    {
        sNewConnectionsHandler.startServer(port);
    }

    public void stopServer()
    {
        sNewConnectionsHandler.stopServer();
    }

}
